package com.atmilan.quartz.controller;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.repository.query.Param;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.atmilan.quartz.model.dto.customs.HgCheckDTO;
import com.atmilan.quartz.model.dto.customs.HgCheckDTO.Body179DTO;
import com.atmilan.quartz.model.dto.customs.HgCheckDTO.GoodsInfoDTO;
import com.atmilan.quartz.model.dto.customs.HgCheckDTO.Head179DTO;
import com.atmilan.quartz.model.entity.crmeb.StoreOrder;
import com.atmilan.quartz.model.entity.crmeb.StoreOrderCustoms;
import com.atmilan.quartz.model.entity.crmeb.StoreOrderInfo;
import com.atmilan.quartz.model.result.crmeb.StoreCartResponse;
import com.atmilan.quartz.service.IStoreOrderCustomsService;
import com.atmilan.quartz.service.IStoreOrderInfoService;
import com.atmilan.quartz.service.IStoreOrderService;
import com.atmilan.quartz.utils.CommonResult;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j2;

/**
 * @author daigb
 * @date:  2021-11-19 13:44    
 *
 */
@Log4j2
@RestController
@RequestMapping("api/custom")
@Api(tags = "海关清关校验")
public class CustomsController {
    @Autowired
    IStoreOrderCustomsService storeOrderCustomsService;
    @Autowired
    IStoreOrderService storeOrderService;
    @Autowired
    IStoreOrderInfoService storeOrderInfoService;
	// 将数据上报海关
	final static String url = "https://customs.chinaport.gov.cn/ceb2grab/grab/realTimeDataUpload";

	/**
	 * 海关抓取数据接口
	 * @param openReq
	 * @return
	 */
    @ApiOperation(value = "清关订单查询")
    @RequestMapping(value = "/platDataOpen", method = RequestMethod.POST)
	public Map<String, Object> doPlatDataOpen(@Param(value="openReq") String openReq) {
		JSONObject object = JSONObject.parseObject(openReq);
		// 异步调用数据报送接口
		log.info("--------------- 异步调用数据报送接口: {} ---------------", openReq);
		repDataApply(object.getString("orderNo"), object.getString("sessionID"), object.getLong("serviceTime"));
		
		// 返回报文给海关
		Map<String, Object> result = new HashMap<>();
		result.put("code", "10000");
		result.put("message", "接收成功!");
		result.put("serviceTime", System.currentTimeMillis());
		return result;
	}
    
    @ApiOperation(value = "轮询待加签数据")
    @RequestMapping(value = "/sign", method = RequestMethod.GET)
    public void doSign2(HttpServletResponse response) throws IOException {
    	List<StoreOrderCustoms> storeOrderCustomsList = storeOrderCustomsService.list(Wrappers.<StoreOrderCustoms>lambdaQuery()
    			.isNotNull(StoreOrderCustoms :: getSessionId)
    			.isNotNull(StoreOrderCustoms :: getPayVerDept)
    			.isNull(StoreOrderCustoms :: getPushSign)
    			);
    	
    	log.info("--------------- 轮询待加签数据数量: {} ---------------", storeOrderCustomsList.size());
    	List<Map<String, Object>> list = new ArrayList<>();
    	for(StoreOrderCustoms customs : storeOrderCustomsList) {
    		Map<String, Object> map = new LinkedHashMap<>();
    		map.put("milanCustomsPushContent", customs.getPushContent());
    		map.put("milanCustomsId", customs.getId());
    		list.add(map);
    	}
    	
    	response.getWriter().println(list);
    }
    
    @ApiOperation(value = "加签数据存储")
    @RequestMapping(value = "/sign", method = RequestMethod.POST)
    public CommonResult<Object> saveSign(@RequestBody List<StoreOrderCustoms> storeOrderCustomsList) {
    	for(StoreOrderCustoms storeOrderCustoms : storeOrderCustomsList) {
    		log.info("--------------- 加签完成返回: {} ---------------", storeOrderCustoms.getPushSign());
    		storeOrderCustomsService.update(Wrappers.<StoreOrderCustoms>lambdaUpdate()
    				.set(StoreOrderCustoms :: getPushSign, storeOrderCustoms.getPushSign())
    				.set(StoreOrderCustoms :: getUpdateTime, new Date())
    				.eq(StoreOrderCustoms :: getId, storeOrderCustoms.getId())
    				);
    	}

        return CommonResult.success();
    }
    
	/**
	 * 向海关返回原始订单数据
	 * @param orderNo
	 * @param sessionID
	 * @return
	 * @throws Exception 
	 */
    @Async
	private void repDataApply(String orderNo, String sessionId, Long serviceTime) {
		// 海关请求保存
		StoreOrderCustoms storeOrderCustoms = storeOrderCustomsService.getOne(Wrappers.<StoreOrderCustoms>lambdaQuery()
				.eq(StoreOrderCustoms :: getOrderNo, orderNo)
				.last("LIMIT 1")
				);
		// 未报关情况下也将数据保存
		if(null == storeOrderCustoms) {
			log.error("--------------- 海关查验异常, 没有该订单报关信息: {} ---------------", orderNo);
			storeOrderCustoms = new StoreOrderCustoms();
			storeOrderCustoms.setOrderNo(orderNo);
			storeOrderCustoms.setSessionId(sessionId);
			storeOrderCustoms.setServiceTime(serviceTime.toString());
			storeOrderCustoms.setOutStatus(true);
			storeOrderCustoms.setPushMsg("海关查验异常, 没有该订单报关信息");
			storeOrderCustoms.setCreateTime(new Date());
			storeOrderCustomsService.save(storeOrderCustoms);
			return;
		}
		
		// 组装参数
		HgCheckDTO entity = getHaiguanOrginData(orderNo, sessionId, storeOrderCustoms);
		if(null == entity) {
			storeOrderCustoms.setSessionId(sessionId);
			storeOrderCustoms.setServiceTime(serviceTime.toString());
			storeOrderCustoms.setOutStatus(true);
			storeOrderCustoms.setOutTime(new Date());
			storeOrderCustoms.setPushMsg("海关查验异常, 没有该商品");
			storeOrderCustomsService.updateById(storeOrderCustoms);
			return;
		}

		// 加签成海关指定数据格式
		StringBuffer sb = new StringBuffer();
		sb.append("\"sessionID\":\"").append(entity.getSessionID()).append("\"").append("||");
		String headerString = JSON.toJSONString(entity.getPayExchangeInfoHead(), SerializerFeature.SortField);
		sb.append("\"payExchangeInfoHead\":\"").append(headerString).append("\"").append("||");
		String listString = JSON.toJSONString(entity.getPayExchangeInfoLists(), SerializerFeature.SortField);
		sb.append("\"payExchangeInfoLists\":\"").append(listString).append("\"").append("||");
		sb.append("\"serviceTime\":\"").append(entity.getServiceTime()).append("\"");
		String signValue = sb.toString();
		
		// 海关数据推送
		storeOrderCustoms.setSessionId(sessionId);
		storeOrderCustoms.setServiceTime(serviceTime.toString());
		storeOrderCustoms.setOutStatus(true);
		storeOrderCustoms.setPushContent(signValue);
		storeOrderCustoms.setPushValue(JSON.toJSONString(entity));
		storeOrderCustoms.setOutTime(new Date());
		storeOrderCustomsService.updateById(storeOrderCustoms);

		log.info("--------------- 海关清关加签串: {} ---------------", signValue);
	}
	
	/**
	 * 构建订单查验对象
	 * @param orderNo
	 * @param sessionID
	 * @return
	 */
	private HgCheckDTO getHaiguanOrginData(String orderNo, String sessionID, StoreOrderCustoms storeOrderCustoms) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
		StoreOrder storeOrder = storeOrderService.getByOrderId(orderNo);
		if(null == storeOrder) {
			log.error("--------------- 海关查验异常, 没有该订单: {} ---------------", orderNo);
			return null;
		}
		List<StoreOrderInfo> infos = storeOrderInfoService.list(Wrappers.<StoreOrderInfo>lambdaQuery()
				.in(StoreOrderInfo :: getId, JSONArray.parseArray(storeOrderCustoms.getInfoIds()))
				);
		
		HgCheckDTO hgCheckDTO = new HgCheckDTO();
//		hgCheckDTO.setCertNo("01719b9f");
		hgCheckDTO.setCertNo("016c525d");
		// 签名值
		hgCheckDTO.setSignValue("");
		hgCheckDTO.setSessionID(sessionID);
		hgCheckDTO.setServiceTime(Instant.now().toEpochMilli() + "");
		
		/** 请求头信息 **/
		Head179DTO head179DTO = new Head179DTO();
		head179DTO.setGuid(sessionID);
		head179DTO.setInitalRequest(storeOrder.getPayParam());
		head179DTO.setInitalResponse(storeOrder.getBackParam());
		// 电商平台代码
//		head179DTO.setEbpCode("3303960B04");
		head179DTO.setEbpCode("3303960EZ4");
		// 支付企业代码
//		head179DTO.setPayCode("4403169D3W");
		head179DTO.setPayCode("310496099C");
		head179DTO.setPayTransactionId(storeOrder.getOutOrderId());
		head179DTO.setTotalAmount(storeOrder.getTotalPrice().doubleValue());
		head179DTO.setCurrency("142");
		head179DTO.setVerDept("3");
		head179DTO.setPayType("1");
		head179DTO.setTradingTime(sdf.format(storeOrder.getPayTime()));
		head179DTO.setNote(storeOrder.getMark());
		hgCheckDTO.setPayExchangeInfoHead(head179DTO);
		
		/** 请求体信息 **/
		List<Body179DTO> body179DTOs = new ArrayList<>();
		Body179DTO body179DTO = new Body179DTO();
		body179DTO.setOrderNo(orderNo);
		// 商品信息
		List<GoodsInfoDTO> goodsInfoDTOs = new ArrayList<>();
		for(StoreOrderInfo info : infos) {
			StoreCartResponse cart = JSON.parseObject(info.getInfo(), StoreCartResponse.class);
			GoodsInfoDTO goodsInfoDTO = new GoodsInfoDTO();
			goodsInfoDTO.setGname(cart.getProductInfo().getStoreName());
			// 商品展示地址?
			goodsInfoDTO.setItemLink("http://prod-customs.suyun999.com:8086/index.html?id=" + info.getProductId());
			goodsInfoDTOs.add(goodsInfoDTO);
		}
		body179DTO.setGoodsInfo(goodsInfoDTOs);
		// 自营商户的收款账户
//		body179DTO.setRecpAccount("1203213109200063060");
		body179DTO.setRecpAccount("1203227009200166333");
		// 社会信用代码
//		body179DTO.setRecpCode("91330302MA2ARYN73H");
		body179DTO.setRecpCode("91330304MA2L4TKLXM");
		// 收款企业名称
//		body179DTO.setRecpName("温州诚品睿奢贸易有限公司");
		body179DTO.setRecpName("浙江速云供应链科技有限公司");
		body179DTOs.add(body179DTO);
		hgCheckDTO.setPayExchangeInfoLists(body179DTOs);
		
		return hgCheckDTO;
	}
    
    @RequestMapping(value = "/jstCode", method = RequestMethod.GET)
    public void get(@RequestParam(required = false) String app_key, @RequestParam(required = false) String code, 
    		@RequestParam(required = false) String state, @RequestParam(required = false) String sign) {

		log.info("--------------- 收到聚水潭回调数据: {} ---------------", app_key + "==" + code + "==" + state + "==" + sign);
    }
	
}

